﻿/********************************************************************
	created:	2015/08/07
	created:	7:8:2015   10:29
	filename: 	LaserAutoCode.cpp
	author:		luhuibing
	
	purpose:	实现组合跳码类
*********************************************************************/
#pragma once
#include "StdAfx.h"
#include "LaserAutoCode.h"

CAutoCode::CAutoCode(void)
{
	Clear();
}

CAutoCode::CAutoCode(LPCTSTR lpstr)
{
	m_nType = AUTO_FIXED;
	m_strCode = lpstr;
}

CAutoCode::~CAutoCode(void)
{
}

AUTO_TYPE CAutoCode::GetType()
{
	return this->m_nType;
}
//////////////////////////////////////////////////////////////////////////
// 固定码
bool CAutoCode::SetFixedAutoCode(CString str)
{
//	if (this->m_nType != AUTO_FILE) return false;
	this->m_strCode = str;
	this->m_nType = AUTO_FIXED;
	return true;
}
bool CAutoCode::GetFixAutoCode(CString &str)
{
	str = this->m_strCode;
	return true;
}

//////////////////////////////////////////////////////////////////////////
// 序列号
// 下一个序列号
bool CAutoCode::NextSN()
{
	if (m_nType != AUTO_SERIALNUM && m_nType != AUTO_PANEL_NO) return false;
	if (m_nModeSN == MODE_SN_USER_DEFINE && m_strSNTemplate[3] == _T("")) return false;
	if (m_bResetByDay && m_strCurrentDay != GetCurrentDayString())
	{
		m_strCurrentDay = GetCurrentDayString();
		ResetSN();
	}
	else
	{
		if (m_nCurMarkCount == 0 || m_nCurMarkCount == m_nMarkCount)
		{
			if (m_nCurMarkCount == m_nMarkCount) m_nCurMarkCount = 0;
			bool bChanged = false;
			int iNum = m_strCurrentSN.GetLength() - 1;
			if (iNum > 0)
			{
				for (int i = iNum; i >= 0; i--)
				{
					UINT nPos = m_strSNTemplate[m_nModeSN].Find(m_strCurrentSN.GetAt(i));
					if (nPos >= m_strSNTemplate[m_nModeSN].GetLength() - m_nStepSN)
					{
						if (!bChanged)
						{
							m_strCurrentSN.SetAt(i, m_strSNTemplate[m_nModeSN].GetAt(nPos - m_strSNTemplate[m_nModeSN].GetLength() + m_nStepSN));
							bChanged = true;
							//					i++;
							continue;
						}
						else if (bChanged)
						{
							if (nPos == m_strSNTemplate[m_nModeSN].GetLength() - 1)
							{
								m_strCurrentSN.SetAt(i, m_strSNTemplate[m_nModeSN].GetAt(0));
								continue;
							}
							else
							{
								m_strCurrentSN.SetAt(i, m_strSNTemplate[m_nModeSN].GetAt(nPos + 1));
								break;
							}
						}
					}
					if (bChanged) m_strCurrentSN.SetAt(i, m_strSNTemplate[m_nModeSN].GetAt(nPos + 1));
					else m_strCurrentSN.SetAt(i, m_strSNTemplate[m_nModeSN].GetAt(nPos + m_nStepSN));
					break;
				}
			}
		}
		m_nCurMarkCount++;
	}
	m_strCode = m_strCurrentSN;
	return true;
}
// 获取当前年月日信息
CString CAutoCode::GetCurrentDayString()
{
	CTime _tCurrent = CTime::GetCurrentTime();
	CString strDay = _tCurrent.Format(_T("%Y%m%d"));
	return strDay;
}
// 设置SN复位
void CAutoCode::SetSNSeset(bool bSNReset)
{
	if (bSNReset)
	{
		if (m_strCurrentDay != GetCurrentDayString())
		{
			m_strCurrentDay = GetCurrentDayString();
//			ResetSN();
		}
	}
	m_bResetByDay = bSNReset;
}
// 序列号重置
void CAutoCode::ResetSN()
{
	m_strCurrentSN = m_strBeginSN;
}

// 获取当前跳码
CString CAutoCode::GetAutoCode(BOOL bPanel)
{
	switch (m_nType)
	{
	case AUTO_SERIALNUM:
		{
			if (m_bResetByDay && m_strCurrentDay != GetCurrentDayString())
			{
				m_strCurrentDay = GetCurrentDayString();
				ResetSN();
				this->m_strCode = m_strCurrentSN;
			}
			else
			{
				this->m_strCode == _T("") ? NextAutoCode() : this->m_strCode;
			}
		}
		break;
	case AUTO_FILE:
		{
			this->m_strCode == _T("") ? NextAutoCode() : this->m_strCode;
		}
		break;
	case AUTO_FIXED:
	case AUTO_DATE:
	case AUTO_TIME:
		NextAutoCode();
	break;
	case AUTO_PANEL_NO:
	{
		// 如果是一块板则只需要开始的跳转计数
		if (bPanel)
		{
			m_nPicsCount = 0;
			this->m_strCode == _T("") ? NextAutoCode() : this->m_strCode;
		}
	}
	break;
	case AUTO_PCS_NO:
	{
		if (bPanel)
			m_nPicsCount=0;
		if (!m_bDemoMode)
		{
			this->m_strCode.Format(_T("%.2d"), m_nPicsCount + 1);
			m_nPicsCount++;
		}
		else
		{
			m_nPicsCount = 0;
			this->m_strCode = _T("01");
		}
	}	
	break;
	default:
		break;
	}
	return this->m_strCode;
}

CString CAutoCode::GetCurrentDate(int dt)
{
	SetDateAutoCode(dt, NULL);
	NextDate();
	CString str;
	switch (dt)
	{
	case MODE_DATE_YEAR_W:
		str = _T("年-");
		break;
	case MODE_DATE_YEAR_A:
		str = _T("年-");
		break;
	case MODE_DATE_MOUNTH:
		str = _T("月-");
		break;
	case MODE_DATE_DAY:
		str = _T("日-");
		break;
	case MODE_DATE_DAY_OF_YEAR:
		str = _T("天-");
		break;
	case MODE_DATE_DAY_OF_WEEK:
		str = _T("星期-");
		break;
	case MODE_DATE_WEEK_OF_YEAR:
		str = _T("周-");
		break;
	default:
		break;
	}
	str += this->m_strCode;
	return str;
}
// 设置模板变量
void CAutoCode::SetDateTemplateString(CString strTemp)
{
	CString str, strTemp1 = _T("123456789ABCDEFGHJKLMNPQRSTUVWXYZ0+-");
	for (size_t i = 0; i < 36; i++)
	{
		str.Format(_T("%c"), strTemp1.GetAt(i));
		m_strDateTemplate[i] = str;
	}
}
// 跳码跳变
bool CAutoCode::NextAutoCode()
{
	if (m_nType == AUTO_SERIALNUM || m_nType == AUTO_PANEL_NO) return NextSN();
	else if (m_nType == AUTO_DATE)  return NextDate();
	else if (m_nType == AUTO_TIME) return NextTime();
	else if (m_nType == AUTO_FILE) return NextFileCode();
	else return true;
}
// SN初始化
void CAutoCode::SetSNAutoCode(CString strBeginSN, CString strCurrSN, CString strMaxSN, UINT nStepSN, UINT nMarkCount,\
	UINT nCurrMarkCount, UINT nModeSN, CString strUserDefineTemplate)
{
	this->m_nType = AUTO_SERIALNUM;
	this->m_strBeginSN = strBeginSN;
	this->m_strCurrentSN = strCurrSN;
	this->m_strMaxSN = strMaxSN;
	this->m_nStepSN = nStepSN;
	this->m_nMarkCount = nMarkCount;
	this->m_nCurMarkCount = nCurrMarkCount;
	this->m_nModeSN = nModeSN;
	this->m_strSNTemplate[3] = strUserDefineTemplate;
	if (strUserDefineTemplate != _T("")) m_bUserDefine = true;
	m_strCode = strCurrSN;
//	NextSN();
}
// 获取序列号参数
bool CAutoCode::GetSNAutoCode(CString &strBeginSN, CString &strCurrSN, CString &strMaxSN, UINT &nStepSN, UINT &nMarkCount,\
	UINT &nCurrMarkCount, UINT &nModeSN, CString &strUserDefineTemplate)
{
	strBeginSN = this->m_strBeginSN;
	strCurrSN = this->m_strCurrentSN;
	strMaxSN = this->m_strMaxSN;
	nStepSN = this->m_nStepSN;
	nMarkCount = this->m_nMarkCount;
	nCurrMarkCount = this->m_nCurMarkCount;
	nModeSN = this->m_nModeSN;
	if (nModeSN > 4) return false;
	strUserDefineTemplate = this->m_strSNTemplate[this->m_nModeSN];
	return true;
}

//////////////////////////////////////////////////////////////////////////
// 日期
// 日期初始化
void CAutoCode::SetDateAutoCode(UINT nModeDate, CStringArray* str)
{
	ASSERT(nModeDate <= MODE_DATE_WEEK_OF_YEAR && nModeDate >= MODE_DATE_YEAR_W);
	this->m_nType = AUTO_DATE;
	this->m_nModeDate = nModeDate;
	if (str)
	{
		for (int i = 0; i < str->GetSize(); i++)
			m_strDateTemplate[i] = str->GetAt(i);
	}
	NextDate();
}
void CAutoCode::SetDateAutoCode(UINT nModeDate, CString strTemp)
{
	if (strTemp == _T(""))
		return;
	this->m_nType = AUTO_DATE;
	this->m_nModeDate = nModeDate;
	for (int i = 0; i < MAX_PATH; i++)
		m_strDateTemplate[i] = _T("");
	for (int i = 0; i < strTemp.GetLength(); i++)
	{
		m_strDateTemplate[i].Format(_T("%c"), strTemp[i]);
	}
}

bool CAutoCode::GetDateAutoCode(UINT &nModeDate)
{
	nModeDate = this->m_nModeDate;
	return true;
}

// 获取数据模板大小
UINT CAutoCode::GetSize(CString str[])
{
	UINT nSize = 0;
	for (int i = 0; i < MAX_PATH; i++)
	{
		if (str[i]!=_T("")) nSize++;
	}
	return nSize;
}

// 清空数据
void CAutoCode::ClearData(CString str[])
{
	int nSize = sizeof(str) / sizeof(str[0]);
	for (int i = 0; i < nSize; i++) str[i] = _T("");
}

// 下一个日期数据
bool CAutoCode::NextDate()
{
	CTime _tCurrent = CTime::GetCurrentTime();
	ASSERT(_tCurrent.GetYear() >= 2010 && _tCurrent.GetYear() <= 2060);
	switch (m_nModeDate)
	{
	case MODE_DATE_UNDEFINE:
		return false;
		break;
	case MODE_DATE_YEAR_W:
		{
			if (GetSize(m_strDateTemplate) > 0)
				m_strCode = m_strDateTemplate[_tCurrent.GetYear()-2010];
			else
				m_strCode = _tCurrent.Format(_T("%Y"));
		}
		break;
	case MODE_DATE_YEAR_1:
		{
			m_strCode = _tCurrent.Format(_T("%y"));
			m_strCode = m_strCode.Right(1);
		}
		break;
	case MODE_DATE_YEAR_A:
		m_strCode = _tCurrent.Format(_T("%y"));
		break;
	case MODE_DATE_MOUNTH:
		{
			if (GetSize(m_strDateTemplate) > 0)
				m_strCode = m_strDateTemplate[_tCurrent.GetMonth()-1];
			else
				m_strCode = _tCurrent.Format(_T("%m"));
		}
		break;
	case MODE_DATE_DAY:
		{
			if (GetSize(m_strDateTemplate) > 0)
			{
				int n = _tCurrent.GetDay();
				m_strCode = m_strDateTemplate[_tCurrent.GetDay() - 1];
			}
			else
				m_strCode = _tCurrent.Format(_T("%d"));
		}
		break;
	case MODE_DATE_DAY_OF_YEAR:
		m_strCode = _tCurrent.Format(_T("%j"));
		break;
	case MODE_DATE_DAY_OF_WEEK:
		{
			if (GetSize(m_strDateTemplate) == 7)
				m_strCode = m_strDateTemplate[_tCurrent.GetDayOfWeek()==1?6:_tCurrent.GetDayOfWeek()-2];
			else
				m_strCode.Format(_T("%d"), _tCurrent.GetDayOfWeek()==1?7:_tCurrent.GetDayOfWeek()-1);
		}
		break;
	case MODE_DATE_WEEK_OF_YEAR:
		{
			CString strTemp = _T("");
			int nIndex = 0;
			int iYear = _tCurrent.GetYear();
			COleDateTime ct(iYear, 1, 1, 0, 0, 0);
			if (ct.GetDayOfWeek() == 1)
			{
				nIndex = StrToInt(_tCurrent.Format(_T("%U")));
			}
			else
			{
				nIndex = StrToInt(_tCurrent.Format(_T("%U"))) + 1;
			}
			strTemp.Format(_T("%.2d"), nIndex);
//			nWeek = _wtoi(_tCurrent.Format(_T("%U")));
			if (GetSize(m_strDateTemplate) == 53)
				m_strCode = m_strDateTemplate[nIndex];
			else
				m_strCode.Format(_T("%.2d"), nIndex);
		}
		break;
	default:
		return false;
		break;
	}
	return true;
}

//////////////////////////////////////////////////////////////////////////
// 时间
// 时间初始化
void CAutoCode::SetTimeAutoCode(UINT nModeTime)
{
	this->m_nType = AUTO_TIME;
	this->m_nModeTime = nModeTime;
	NextTime();
}

bool CAutoCode::GetTimeAutoCode(UINT &nModeTime)
{
	nModeTime = this->m_nModeTime;
	return true;
}

// 下一个时间数据
bool CAutoCode::NextTime()
{
	ASSERT(m_nModeTime >= MODE_TIME_HOUR_W);
	CTime _tCurrent = CTime::GetCurrentTime();
	switch (m_nModeTime)
	{
	case MODE_TIME_HOUR_W:				// 24小时制
		m_strCode = _tCurrent.Format(_T("%H"));
		break;
	case MODE_TIME_HOUR_A:				// 12小时制
		m_strCode = _tCurrent.Format(_T("%I"));
		break;
	case MODE_TIME_MINUTES:				// 分钟
		m_strCode = _tCurrent.Format(_T("%M"));
		break;
	case MODE_TIME_SECONDS:				// 秒
		m_strCode = _tCurrent.Format(_T("%S"));
		break;
	case MODE_TIME_MILLISECONDS:		// 毫秒
		{
			SYSTEMTIME  _cursystme;
			::GetLocalTime(&_cursystme);
			m_strCode.Format(_T("%.3d"), _cursystme.wMilliseconds);
		}
		break;
	case MODE_TIME_PERIOD:				// 时间段
		{
			
		}
		break;
	default:
		return false;
		break;
	}
	return true;
}

//////////////////////////////////////////////////////////////////////////
// 文件初始化
void CAutoCode::SetFileAutoCode(CString strFile)
{
	if (::GetFileAttributes(strFile) == -1)
	{
// 		return false;
	}
	else
	{
		this->m_nType = AUTO_FILE;
		this->m_strFilePath = strFile;
//		return true;
	}
}
bool CAutoCode::GetFileAutoCode(CString &strFile)
{
	strFile = this->m_strFilePath;
	return true;
}

bool CAutoCode::NextFileCode()
{
	CString strLog;
	if (-1 == GetFileAttributes(m_strFilePath))
	{
//		LOG(DEBUG) << _T("文件不存在");
		return false;
	}
	CString strCode = _T("");
	CStdioFile File;
	if (File.Open(m_strFilePath, CFile::modeReadWrite | CFile::typeText))
	{
		CString __str = _T("");
		File.SeekToEnd();
		ULONGLONG _tMaxLen = File.GetLength();
		_tMaxLen -= 16;
		File.Seek(_tMaxLen, CFile::begin);
		char _byte[2] = { 0 };
		File.Read(_byte, 1);
		BOOL bMarked = _byte[0] == 0x0e ? TRUE : FALSE;
		if (bMarked)
		{
			File.ReadString(__str);
			DWORD dwCurrPos = StrToInt(__str.Right(7));
			File.Seek(dwCurrPos, CFile::begin);
		}
		else
		{
			File.SeekToBegin();
			byte buf[3];
			File.Read(buf, 3);
			if (buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
			{
			}
			else
			{
				File.SeekToBegin();
			}
		}
		File.ReadString(strCode);
		m_strCode = strCode;
		DWORD nMaxPos = File.GetLength();
		DWORD nCurPos = File.GetPosition();
		__str.Format(_T("\xe%.7d:%.7d"), nMaxPos, nCurPos);
		DWORD nLastWrite = bMarked ? (nMaxPos - 16) : nMaxPos;
		File.Seek(nLastWrite, CFile::begin);
		File.WriteString(__str);
		File.Close();
		return true;
	}
	else
	{
		int nError = GetLastError();
		CString strErr = _T("");
		strErr.Format(_T("打开文件异常,错误代码:%d"), nError);
		return false;
	}
}

void CAutoCode::Clear()
{
	m_strCurrentDay = m_strCode = _T("");
	m_nPicsCount = 0;
	m_bResetByDay = m_bUserDefine = false;
	m_strSNTemplate[0] = _T("0123456789");
	m_strSNTemplate[1] = _T("0123456789ABCDEF");
	m_strSNTemplate[2] = _T("0123456789abcdef");
	m_strSNTemplate[3] = _T("");
	m_bDemoMode = false;
	m_nType = AUTO_FIXED;
	m_strBeginSN = _T("0001");
	m_strCurrentSN = _T("0001");
	m_strMaxSN = _T("9999");
	m_nStepSN = 1;
	m_nMarkCount = 1;
	m_nCurMarkCount = 0;
	m_nModeSN = MODE_SN_DEC;

	m_nModeDate = MODE_DATE_YEAR_W;
	//	m_strDateTemplate.RemoveAll();
	for (int i = 0; i <MAX_PATH; i++) m_strDateTemplate[i] = _T("");

	m_nModeTime = MODE_TIME_HOUR_W;
	m_strFilePath = _T("");
}


//////////////////////////////////////////////////////////////////////////
CLaserAutoCode::CLaserAutoCode(void)
{
	m_strName = _T("");
	m_bDemoModle = false;
}
CLaserAutoCode::~CLaserAutoCode(void)
{

}

void CLaserAutoCode::Add(CAutoCode autocode)
{
 	m_vAutoCode.push_back(autocode);
}

void CLaserAutoCode::Add(LPCTSTR lpstr)
{
	m_vAutoCode.push_back(CAutoCode(lpstr));
}

bool CLaserAutoCode::MoveNext(UINT nIndex)
{
 	if (nIndex >= m_vAutoCode.size() || nIndex < 0) return false;

	vector<CAutoCode>::iterator iter = m_vAutoCode.begin();
	UINT n = 0;
	CAutoCode temp;
	BOOL bInsert = FALSE;
	while (iter != m_vAutoCode.end())
	{
		if (n == nIndex)
		{
			if (!bInsert)
			{
				temp = *iter;
				m_vAutoCode.erase(iter);
				bInsert = TRUE;
				iter = m_vAutoCode.begin();
				n = 0;
				nIndex += 1;
				continue;
			}
			else
			{
				m_vAutoCode.insert(iter, temp);
				bInsert = FALSE;
				break;
			}
		}
		iter++, n++;
	}
	if (bInsert)
	{
		m_vAutoCode.insert(iter, temp);
	}
	return true;
}
bool CLaserAutoCode::MovePrev(UINT nIndex)
{
	if (nIndex >= m_vAutoCode.size() || nIndex <= 0) return false;

	vector<CAutoCode>::iterator iter = m_vAutoCode.begin();
	UINT n = 0;
	CAutoCode temp;
	BOOL bInsert = FALSE;
	while (iter != m_vAutoCode.end())
	{
		if (n == nIndex)
		{
			if (!bInsert)
			{
				temp = *iter;
				m_vAutoCode.erase(iter);
				bInsert = TRUE;
				iter = m_vAutoCode.begin();
				n = 0;
				nIndex -= 1;
				continue;
			}
			else
			{
				m_vAutoCode.insert(iter, temp);
				bInsert = FALSE;
				break;
			}
		}
		iter++, n++;
	}
	if (bInsert)
	{
		m_vAutoCode.insert(iter, temp);
	}
	return true;
}
bool CLaserAutoCode::DeleteIndex(UINT nIndex)
{
	vector<CAutoCode>::iterator iter = m_vAutoCode.begin();
	UINT n = 0;
	while (iter != m_vAutoCode.end())
	{
		if (n++ == nIndex)
		{
			m_vAutoCode.erase(iter);
			break;
		}
		iter++;
	}
	return true;
}
CString CLaserAutoCode::GetLaserCode(BOOL bPanel)
{
	vector<CAutoCode>::iterator iter = m_vAutoCode.begin();
	CString strRet = _T("");
	while (iter != m_vAutoCode.end())
	{
		if (iter->GetType() == AUTO_PCS_NO)
			iter->DemoModle(m_bDemoModle);

		strRet += iter->GetAutoCode(bPanel);
		iter++;
	}
	return strRet;
}
bool CLaserAutoCode::GetNextLaserCode()
{
	vector<CAutoCode>::iterator iter = m_vAutoCode.begin();
	while(iter != m_vAutoCode.end())
	{
		if (!iter->NextAutoCode()) return false;
		iter++;
	}
	return true;
}
bool CLaserAutoCode::HasePanelCode()
{
	vector<CAutoCode>::iterator iter = m_vAutoCode.begin();
	while (iter != m_vAutoCode.end())
	{
		if (iter->GetType() == AUTO_PANEL_NO)
			return true;
		iter++;
	}
	return false;

}
CString CLaserAutoCode::GetAt(int pos)
{
	if (pos >= (int)m_vAutoCode.size() || pos < 0) return _T("");
	return m_vAutoCode.at(pos).GetAutoCode();
}

CAutoCode* CLaserAutoCode::at(int pos)
{
	if (pos > (int)m_vAutoCode.size() || pos < 0) return NULL;
	return &m_vAutoCode.at(pos);
}


int CLaserAutoCode::Size()
{
	return m_vAutoCode.size();
}

//////////////////////////////////////////////////////////////////////////
CRandomStr::CRandomStr(void)
{
	this->m_strdata = _T("");
}

CRandomStr::~CRandomStr(void)
{
	this->m_strdata = _T("");
}

CRandomStr::CRandomStr(CString str)
{
	this->m_strdata = str;
}

void CRandomStr::SetRandomTemplate(CString strTemplate)
{
	this->m_strdata = strTemplate;
}

CString CRandomStr::GetRandomString(int nSize)
{
	srand((unsigned)time(NULL));
	CString strTemp = _T("");
	for (int i = 0; i < nSize; i++)
		strTemp += this->m_strdata.GetAt(rand()%(this->m_strdata.GetLength()));
	return strTemp;
}
